// clang-format off
#include "types.h"
#include "x86.h"
#include "defs.h"
#include "date.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
// clang-format on
int sys_fork(void) { return fork(); }

int sys_exit(void) {
    exit();
    return 0; // not reached
}

int sys_wait(void) { return wait(); }

int sys_kill(void) {
    int pid;

    if (argint(0, &pid) < 0)
        return -1;
    return kill(pid);
}

int sys_getpid(void) { return myproc()->pid; }

#define LAZY_SBRK // 即时分配

int sys_sbrk(void) {
    uint addr; // 当前指针
    int n;     // 增量

    // 获取参数
    if (argint(0, &n) < 0)
        return -1;
    addr = myproc()->sz;

#ifdef LAZY_SBRK
    uint top = addr + n;

    // DEBUG
    // cprintf("DEBUG: sys_sbrk()\n");
    // cprintf("    addr = 0x%x\n", addr);
    // cprintf("    diff = 0x%x\n", n);
    // cprintf("    top  = 0x%x\n", top);

    if (top >= KERNBASE) {
        // 检查内存是否越界
        // 下溢也会触发这段
        return -1;
    } else if (top > myproc()->sz) {
        // 申请内存
        // 延迟内存分配
        // cprintf("    type = alloc\n");
        myproc()->sz = top;
    } else if (top < myproc()->sz) {
        // 释放内存
        // cprintf("    type = free\n");
        deallocuvm(myproc()->pgdir, addr, top);
        myproc()->sz = top;
    } else {
        // 什么都不做
    }
#else
    if (growproc(n) < 0)
        return -1;
#endif
    return addr;
}

int sys_sleep(void) {
    int n;
    uint ticks0;

    if (argint(0, &n) < 0)
        return -1;
    acquire(&tickslock);
    ticks0 = ticks;
    while (ticks - ticks0 < n) {
        if (myproc()->killed) {
            release(&tickslock);
            return -1;
        }
        sleep(&ticks, &tickslock);
    }
    release(&tickslock);
    return 0;
}

// return how many clock tick interrupts have occurred
// since start.
int sys_uptime(void) {
    uint xticks;

    acquire(&tickslock);
    xticks = ticks;
    release(&tickslock);
    return xticks;
}

// 获取当前时间
int sys_date(void) {
    struct rtcdate *r;
    if (argptr(0, (void *)&r, sizeof(struct rtcdate)) < 0) {
        return -1;
    }

    cmostime(r);
    return 0;
}

// 系统中断提示
int sys_alarm(void) {
    int ticks;
    void (*handler)(void);

    if (argint(0, &ticks) < 0 || ticks <= 0 || argptr(1, (char **)&handler, 1) < 0) {
        return -1;
    }

    struct proc *curproc = myproc();
    curproc->alarm_curTick = 0;
    curproc->alarm_totTick = ticks;
    curproc->alarm_flagInHandler = 0;
    curproc->alarm_handler = handler;

    return 0;
}

// 系统中断恢复

int sys_alarm_warpper(void) {
    struct proc *curproc = myproc();
    struct trapframe *tf = curproc->tf;

    if (curproc->alarm_totTick <= 0 || curproc->alarm_flagInHandler != 1) {
        return -1;
    }
    curproc->alarm_flagInHandler = 0;

    /* 恢复寄存器 */

    // 取出旧值
    int eip, eax, edx, ecx, ebx, ebp, esi, edi;
    if (argint(-1, &edi) < 0 || argint(0, &esi) < 0 || argint(1, &ebp) < 0 ||
        argint(2, &ebx) < 0 || argint(3, &ecx) < 0 || argint(4, &edx) < 0 ||
        argint(5, &eax) < 0 || argint(6, &eip) < 0) {
        return -1;
    }

    // 赋值
    tf->eip = eip;
    tf->eax = eax;
    tf->edx = edx;
    tf->ecx = ecx;
    tf->ebx = ebx;
    tf->ebp = ebp;
    tf->esi = esi;
    tf->edi = edi;

    // DEBUG
    // cprintf("After alarm :\n");
    // cprintf("\t%%esp = %x\n", tf->esp + 0x20);
    // cprintf("\t%%eip = %x @%p\n", tf->eip, tf->esp + 0x1c);

    // cprintf("\t%%eax = %x @%p\n", tf->eax, tf->esp + 0x18);
    // cprintf("\t%%edx = %x @%p\n", tf->edx, tf->esp + 0x14);
    // cprintf("\t%%ecx = %x @%p\n", tf->ecx, tf->esp + 0x10);

    // cprintf("\t%%ebx = %x @%p\n", tf->ebx, tf->esp + 0x0c);
    // cprintf("\t%%ebp = %x @%p\n", tf->ebp, tf->esp + 0x08);
    // cprintf("\t%%esi = %x @%p\n", tf->esi, tf->esp + 0x04);
    // cprintf("\t%%edi = %x @%p\n", tf->edi, tf->esp);

    // 恢复 ESP
    tf->esp += 0x20;

    return 0;
}